package com.jsy.common.util.m3u8;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * M3U8视频合并工具类
 * 支持解析M3U8文件并合并TS片段为完整视频
 */
public class M3U8Merger {
    private String m3u8Path;              // M3U8文件路径(本地或URL)
    private String tsFilesDir;            // TS片段所在目录
    private String outputPath;            // 输出文件路径
    private boolean isUrl = false;        // 是否为URL
    private boolean deleteTsAfterMerge = false;  // 合并后是否删除TS文件
    private MergeListener listener;       // 合并监听器

    // 用于匹配M3U8中的TS片段URL
    private static final Pattern TS_URL_PATTERN = Pattern.compile("^[^#].*\\.(ts|mp4|m4s)$");
    // 用于匹配M3U8中的EXT-X-STREAM-INF标签(多层M3U8)
    private static final Pattern STREAM_INF_PATTERN = Pattern.compile("#EXT-X-STREAM-INF:.*\\s(.*m3u8)");

    public M3U8Merger(String m3u8Path, String tsFilesDir, String outputPath) {
        this.m3u8Path = m3u8Path;
        this.tsFilesDir = tsFilesDir;
        this.outputPath = outputPath;
        this.isUrl = m3u8Path.startsWith("http");
    }

    // 设置合并后是否删除TS文件
    public M3U8Merger setDeleteTsAfterMerge(boolean deleteTsAfterMerge) {
        this.deleteTsAfterMerge = deleteTsAfterMerge;
        return this;
    }

    // 设置合并监听器
    public M3U8Merger setListener(MergeListener listener) {
        this.listener = listener;
        return this;
    }

    // 合并M3U8视频
    public void merge() throws IOException {
        // 解析M3U8文件获取TS片段列表
        List<String> tsFiles = parseM3U8(m3u8Path);
        if (tsFiles.isEmpty()) {
            throw new IOException("未找到TS片段");
        }

        // 创建输出文件的父目录
        File outputFile = new File(outputPath);
        File parentDir = outputFile.getParentFile();
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        }

        // 合并TS文件
        mergeTsFiles(tsFiles);

        if (listener != null) {
            listener.onMergeComplete(outputPath);
        }
    }

    // 解析M3U8文件获取TS片段列表
    private List<String> parseM3U8(String m3u8Path) throws IOException {
        List<String> tsFiles = new ArrayList<>();
        List<String> lines = readM3U8Lines(m3u8Path);
        
        for (String line : lines) {
            line = line.trim();
            
            // 处理多层M3U8
            Matcher streamMatcher = STREAM_INF_PATTERN.matcher(line);
            if (streamMatcher.find()) {
                String subM3U8Path = streamMatcher.group(1);
                if (isUrl) {
                    subM3U8Path = resolveUrl(m3u8Path, subM3U8Path);
                }
                tsFiles.addAll(parseM3U8(subM3U8Path));
                continue;
            }
            
            // 处理TS片段
            Matcher tsMatcher = TS_URL_PATTERN.matcher(line);
            if (tsMatcher.matches()) {
                String tsFile = line;
                if (isUrl) {
                    // 从URL提取文件名
                    int lastSlashIndex = tsFile.lastIndexOf('/');
                    if (lastSlashIndex != -1) {
                        tsFile = tsFile.substring(lastSlashIndex + 1);
                    }
                }
                tsFiles.add(tsFile);
            }
        }
        
        return tsFiles;
    }

    // 读取M3U8文件内容
    private List<String> readM3U8Lines(String path) throws IOException {
        List<String> lines = new ArrayList<>();
        
        if (isUrl) {
            // 从URL读取
            URL url = new URL(path);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestProperty("User-Agent", "Mozilla/5.0");
            
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    lines.add(line);
                }
            }
        } else {
            // 从本地文件读取
            try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    lines.add(line);
                }
            }
        }
        
        return lines;
    }

    // 解析相对URL为绝对URL
    private String resolveUrl(String baseUrl, String relativeUrl) {
        if (relativeUrl.startsWith("http")) {
            return relativeUrl;
        }
        
        int lastSlashIndex = baseUrl.lastIndexOf('/');
        if (lastSlashIndex != -1) {
            return baseUrl.substring(0, lastSlashIndex + 1) + relativeUrl;
        }
        
        return relativeUrl;
    }

    // 合并TS文件
    private void mergeTsFiles(List<String> tsFiles) throws IOException {
        int totalFiles = tsFiles.size();
        int mergedFiles = 0;
        
        try (FileOutputStream fos = new FileOutputStream(outputPath);
             FileChannel outChannel = fos.getChannel()) {
            
            for (String tsFile : tsFiles) {
                File file = new File(tsFilesDir, tsFile);
                if (!file.exists()) {
                    System.err.println("警告: 文件不存在 - " + file.getAbsolutePath());
                    continue;
                }
                
                try (FileInputStream fis = new FileInputStream(file);
                     FileChannel inChannel = fis.getChannel()) {
                    
                    inChannel.transferTo(0, inChannel.size(), outChannel);
                    
                    mergedFiles++;
                    if (listener != null) {
                        listener.onProgress(mergedFiles, totalFiles);
                    }
                }
            }
        }
        
        // 如果启用了删除选项，合并完成后删除TS文件
        if (deleteTsAfterMerge) {
            deleteTsFiles(tsFiles);
        }
    }

    // 删除TS文件
    private void deleteTsFiles(List<String> tsFiles) {
        for (String tsFile : tsFiles) {
            File file = new File(tsFilesDir, tsFile);
            if (file.exists()) {
                if (!file.delete()) {
                    System.err.println("无法删除文件: " + file.getAbsolutePath());
                }
            }
        }
    }

    // 合并监听器接口
    public interface MergeListener {
        void onProgress(int completed, int total);
        void onMergeComplete(String outputPath);
    }

    // 示例用法
    public static void main(String[] args) {
        String m3u8Path = "https://example.com/stream/index.m3u8";  // 或本地文件路径
        String tsFilesDir = "./downloads";
        String outputPath = "./merged_video.mp4";
        
        try {
            new M3U8Merger(m3u8Path, tsFilesDir, outputPath)
                .setDeleteTsAfterMerge(true)
                .setListener(new MergeListener() {
                    @Override
                    public void onProgress(int completed, int total) {
                        System.out.printf("合并进度: %.2f%% (%d/%d)\n", 
                            (completed * 100.0 / total), completed, total);
                    }
                    
                    @Override
                    public void onMergeComplete(String outputPath) {
                        System.out.println("合并完成: " + outputPath);
                    }
                })
                .merge();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}